package com.shouyun.common.utils;

import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;

/**
 * BigDecimal运算工具类
 * 因方法较多，可直接搜索关键字(加减乘除、比对、格式化)找到相应代码段
 *
 * @author Mark
 */
public class BigDecimalUtils {
    //TODO 加减乘除 start

    /**
     * 除法-保留两位小数并四舍五入
     *
     * @param num1
     * @param num2
     * @return
     */
    public static BigDecimal divideTooRounding(BigDecimal num1, BigDecimal num2) {
        return divide(num1, num2, 2, true);
    }

    public static BigDecimal divideTooRounding(String num1Str, String num2Str) {
        BigDecimal num1 = new BigDecimal(num1Str);
        BigDecimal num2 = new BigDecimal(num2Str);
        return divide(num1, num2, 2, true);
    }

    /**
     * 除法-保留两位小数并不四舍五入
     *
     * @param num1
     * @param num2
     * @return
     */
    public static BigDecimal divideTooNotRounding(BigDecimal num1, BigDecimal num2) {
        return divide(num1, num2, 2, false);
    }

    public static BigDecimal divideTooNotRounding(String num1Str, String num2Str) {
        BigDecimal num1 = new BigDecimal(num1Str);
        BigDecimal num2 = new BigDecimal(num2Str);
        return divide(num1, num2, 2, false);
    }

    public static BigDecimal divideTooNotRounding(BigDecimal num1, String num2Str) {
        BigDecimal num2 = new BigDecimal(num2Str);
        return divide(num1, num2, 2, false);
    }


    /**
     * 乘法-保留两位小数并四舍五入
     *
     * @param num1
     * @param num2
     * @return
     */
    public static BigDecimal multiplyTooRounding(BigDecimal num1, BigDecimal num2) {
        return multiply(num1, num2, 2, true);
    }

    public static BigDecimal multiplyTooRounding(String num1Str, String num2Str) {
        BigDecimal num1 = new BigDecimal(num1Str);
        BigDecimal num2 = new BigDecimal(num2Str);
        return multiply(num1, num2, 2, true);
    }

    /**
     * 乘法-保留两位小数并不四舍五入
     *
     * @param num1
     * @param num2
     * @return
     */
    public static BigDecimal multiplyTooNotRounding(BigDecimal num1, BigDecimal num2) {
        return multiply(num1, num2, 2, false);
    }

    public static BigDecimal multiplyTooNotRounding(String num1Str, String num2Str) {
        BigDecimal num1 = new BigDecimal(num1Str);
        BigDecimal num2 = new BigDecimal(num2Str);
        return multiply(num1, num2, 2, false);
    }

    public static BigDecimal multiplyTooNotRounding(BigDecimal num1, String num2Str) {
        BigDecimal num2 = new BigDecimal(num2Str);
        return multiply(num1, num2, 2, false);
    }


    /**
     * 加法-保留两位小数并四舍五入
     *
     * @param num1
     * @param num2
     * @return
     */
    public static BigDecimal addTooRounding(BigDecimal num1, BigDecimal num2) {
        return add(num1, num2, 2, true);
    }

    public static BigDecimal addTooRounding(String num1Str, String num2Str) {
        BigDecimal num1 = new BigDecimal(num1Str);
        BigDecimal num2 = new BigDecimal(num2Str);
        return add(num1, num2, 2, true);
    }

    /**
     * 加法-保留两位小数并不四舍五入
     *
     * @param num1
     * @param num2
     * @return
     */
    public static BigDecimal addTooNotRounding(BigDecimal num1, BigDecimal num2) {
        return add(num1, num2, 2, false);
    }

    public static BigDecimal addTooNotRounding(String num1Str, String num2Str) {
        BigDecimal num1 = new BigDecimal(num1Str);
        BigDecimal num2 = new BigDecimal(num2Str);
        return add(num1, num2, 2, false);
    }

    /**
     * 减法-保留两位小数并四舍五入
     *
     * @param num1
     * @param num2
     * @return
     */
    public static BigDecimal subtractTooRounding(BigDecimal num1, BigDecimal num2) {
        return subtract(num1, num2, 2, true);
    }

    public static BigDecimal subtractTooRounding(String num1Str, String num2Str) {
        BigDecimal num1 = new BigDecimal(num1Str);
        BigDecimal num2 = new BigDecimal(num2Str);
        return subtract(num1, num2, 2, true);
    }

    /**
     * 减法-保留两位小数并不四舍五入
     *
     * @param num1
     * @param num2
     * @return
     */
    public static BigDecimal subtractTooNotRounding(BigDecimal num1, BigDecimal num2) {
        return subtract(num1, num2, 2, false);
    }

    public static BigDecimal subtractTooNotRounding(String num1Str, String num2Str) {
        BigDecimal num1 = new BigDecimal(num1Str);
        BigDecimal num2 = new BigDecimal(num2Str);
        return subtract(num1, num2, 2, false);
    }

    /**
     * 过滤小数点，只保留两位,四舍五入
     *
     * @param num
     * @return
     */
    public static BigDecimal filterDecimalPointTooRounding(String numStr) {
        if (StringUtils.isBlank(numStr)) {
            return null;
        }
        BigDecimal num = new BigDecimal(numStr);
        return filterDecimalPoint(num, 2, true);
    }

    public static BigDecimal filterDecimalPointTooRounding(BigDecimal num) {
        return filterDecimalPoint(num, 2, true);
    }

    /**
     * 过滤小数点，只保留两位,不四舍五入
     *
     * @param num
     * @return
     */
    public static BigDecimal filterDecimalPointTooNotRounding(String numStr) {
        if (StringUtils.isBlank(numStr)) {
            numStr = "0";
        }
        BigDecimal num = new BigDecimal(numStr);
        return filterDecimalPoint(num, 2, false);
    }

    public static BigDecimal filterDecimalPointTooNotRounding(BigDecimal num) {
        return filterDecimalPoint(num, 2, false);
    }


    /**
     * 除法
     *
     * @param num1       被除数
     * @param num2       除数
     * @param scale      小数位
     * @param isRounding 是否四舍五入
     * @return
     */
    public static BigDecimal divide(BigDecimal num1, BigDecimal num2, int scale, boolean isRounding) {
        if (num1 == null) {
            num1 = new BigDecimal(0);
        }
        if (num2 == null) {
            num2 = new BigDecimal(0);
        }
        int roundingMode = isRounding ? BigDecimal.ROUND_HALF_UP : BigDecimal.ROUND_DOWN;
        return num1.divide(num2, scale, roundingMode);
    }

    /**
     * 乘法
     *
     * @param num1       被乘数
     * @param num2       乘数
     * @param scale      小数位
     * @param isRounding 是否四舍五入
     * @return
     */
    public static BigDecimal multiply(BigDecimal num1, BigDecimal num2, int scale, boolean isRounding) {
        if (num1 == null) {
            num1 = new BigDecimal(0);
        }
        if (num2 == null) {
            num2 = new BigDecimal(0);
        }
        int roundingMode = isRounding ? BigDecimal.ROUND_HALF_UP : BigDecimal.ROUND_DOWN;
        return num1.multiply(num2).setScale(scale, roundingMode);
    }

    /**
     * 加法
     *
     * @param num1
     * @param num2
     * @param scale      小数位
     * @param isRounding 是否四舍五入
     * @return
     */
    public static BigDecimal add(BigDecimal num1, BigDecimal num2, int scale, boolean isRounding) {
        if (num1 == null) {
            num1 = new BigDecimal(0);
        }
        if (num2 == null) {
            num2 = new BigDecimal(0);
        }
        int roundingMode = isRounding ? BigDecimal.ROUND_HALF_UP : BigDecimal.ROUND_DOWN;
        return num1.add(num2).setScale(scale, roundingMode);
    }

    /**
     * 减法
     *
     * @param num1
     * @param num2
     * @param scale      小数位
     * @param isRounding 是否四舍五入
     * @return
     */
    public static BigDecimal subtract(BigDecimal num1, BigDecimal num2, int scale, boolean isRounding) {
        if (num1 == null) {
            num1 = new BigDecimal(0);
        }
        if (num2 == null) {
            num2 = new BigDecimal(0);
        }
        int roundingMode = isRounding ? BigDecimal.ROUND_HALF_UP : BigDecimal.ROUND_DOWN;
        return num1.subtract(num2).setScale(scale, roundingMode);
    }
    //TODO 加减乘除 end

    //TODO 比对 start

    /**
     * num1大于num2返回true
     *
     * @param num1
     * @param num2
     * @return
     */
    public static Boolean gt(BigDecimal num1, BigDecimal num2) {
        if (num1 == null || num2 == null) {
            return null;
        }
        if (num1.compareTo(num2) == 1) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * num1大于等于num2返回true
     *
     * @param num1
     * @param num2
     * @return
     */
    public static Boolean gtAndEq(BigDecimal num1, BigDecimal num2) {
        if (num1 == null || num2 == null) {
            return null;
        }
        if (num1.compareTo(num2) == 1 || num1.compareTo(num2) == 0) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * num1小于num2返回true
     *
     * @param num1
     * @param num2
     * @return
     */
    public static Boolean lt(BigDecimal num1, BigDecimal num2) {
        if (num1 == null || num2 == null) {
            return null;
        }
        if (num1.compareTo(num2) == -1) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * num1小于等于num2返回true
     *
     * @param num1
     * @param num2
     * @return
     */
    public static Boolean ltAndEq(BigDecimal num1, BigDecimal num2) {
        if (num1 == null || num2 == null) {
            return null;
        }
        if (num1.compareTo(num2) == -1 || num1.compareTo(num2) == 0) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * num1等于num2返回true
     *
     * @param num1
     * @param num2
     * @return
     */
    public static Boolean eq(BigDecimal num1, BigDecimal num2) {
        if (num1 == null || num2 == null) {
            return null;
        }
        if (num1.compareTo(num2) == 0) {
            return true;
        } else {
            return false;
        }
    }
    //TODO 比对 end

    //TODO 格式化处理 start

    /**
     * 过滤小数点，只保留两位
     *
     * @param num
     * @param scale      小数位
     * @param isRounding 是否四舍五入
     * @return
     */
    public static BigDecimal filterDecimalPoint(BigDecimal num, int scale, boolean isRounding) {
        if (num == null) {
            num = BigDecimal.ZERO;
        }
        int roundingMode = isRounding ? BigDecimal.ROUND_HALF_UP : BigDecimal.ROUND_DOWN;
        return num.setScale(scale, roundingMode);
    }

    public static BigDecimal filterDecimalPoint(Integer numInt, int scale, boolean isRounding) {
        if (numInt == null) {
            numInt = 0;
        }
        BigDecimal num = new BigDecimal(numInt);
        int roundingMode = isRounding ? BigDecimal.ROUND_HALF_UP : BigDecimal.ROUND_DOWN;
        return num.setScale(scale, roundingMode);
    }

    /**
     * 强转为BigDecimal
     *
     * @param num
     * @return
     */
    public static BigDecimal parse(int num) {
        return new BigDecimal(num);
    }
    //TODO 格式化处理 end
}
